package com.cantor.consumer.pojo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.cantor.common.exception.NoSuchProviderOfServiceAvailableException;
import com.cantor.consumer.discovery.ServiceDiscoverer;
import com.cantor.consumer.proxy.ServiceProxy;
import com.cantor.consumer.proxy.impl.DefaultServiceProxyImpl;
import com.cantor.core.center.RegistrationCenter;
import com.cantor.core.config.CantorAppConfig;
import com.cantor.core.config.CantorAppConfigProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.List;

@Accessors(chain = true)
@Slf4j
public class ServiceRef<T> {

    /**
     * 参数
     */
    // 远程服务版本
    @Getter
    @Setter
    private String version = "";

    // 负载均衡策略
    @Getter
    @Setter
    private String loadBalance = "";

    // 服务执行多久算超时?
    @Getter
    @Setter
    private int timeout;

    // 集群容错:重试次数
    @Getter
    @Setter
    private int retries;

    // 服务降级:强制执行策略,例如force:return null, fail:return null
    @Getter
    @Setter
    private String mock = "";

    /**
     * 必须要设置的组件, app, center,服务接口, 服务发现者 等
     */
    // 应用配置
    @Getter
    @Setter
    private CantorAppConfig appConfig;

    // 注册中心
    @Getter
    @Setter
    private RegistrationCenter center;

    // 要被代理的类
    @Getter
    @Setter
    private Class<T> service;

    // 服务发现者
    @Getter
    @Setter
    private ServiceDiscoverer discoverer;

    /**
     * 非对外暴露组件和参数
     */
    // 本ServiceRef的代理帮助对象
    private ServiceProxy proxy;

    // 该服务在远程注册中心所有对应的provider节点
    private List<String> nodes;

    // Getter: 让nodes只读, 不可修改.
    public Collection<String> getNodes() {
        return CollUtil.unmodifiable(nodes);
    }

    /**
     * 方法
     */
    // 获得代理类
    public T get() {
        // 初始化
        init();
        // 产出代理类
        return proxy.ref();
    }

    public void refreshNodeList() {
        log.trace("{}刷新节点信息", service.getName());
        // 根据Class得到服务名
        String serviceNameWithVersion = service.getName();
        if (StrUtil.isNotEmpty(version)) {
            serviceNameWithVersion += ":" + version;
        }
        this.nodes = discoverer.discover(center, serviceNameWithVersion);
    }

    // 初始化, 负责从center找到该服务对应的所有
    private void init() {
        // 根据Class得到服务名
        String serviceNameWithVersion = service.getName();
        if (StrUtil.isNotEmpty(version)) {
            serviceNameWithVersion += ":" + version;
        }

        // 初始化参数
        CantorAppConfigProperties.ConsumerConfig consumerConfig = appConfig.getProperties().getConsumerConfig();
        if (StrUtil.isBlank(version)) {
            setVersion(consumerConfig.getVersion());
        }
        if (StrUtil.isBlank(loadBalance)) {
            setLoadBalance(consumerConfig.getLoadBalance());
        }
        if (0 == timeout) {
            setTimeout(consumerConfig.getTimeout());
        }
        if (0 == retries) {
            setRetries(consumerConfig.getRetries());
        }
        if (StrUtil.isBlank(mock)) {
            setMock(consumerConfig.getMock());
        }
        // 启动center
        center.run();
        // 使用discoverer的discover方法得到该服务所有远程地址nodes.
        List<String> nodes = discoverer.discover(center, serviceNameWithVersion);
        if (CollUtil.isEmpty(nodes)) {
            throw new NoSuchProviderOfServiceAvailableException(serviceNameWithVersion);
        }
        // 给this.nodes复制
        this.nodes = nodes;
        // 给proxy赋值
        proxy = new DefaultServiceProxyImpl(this);
    }


}
